#include "Box.h"
#include "Const.h"
#include "Game.h"

/**
 * 构造方法。
 * @param type      类型
 * @param x, y      左上角坐标
 * @param bitmap    后台缓冲位图
 * @param back      背后对象
 */
Box::Box(BaseGameObject* back, QPixmap* bitmap, Type type, int x, int y) :
    BaseGameObject(bitmap, type, x, y),
    mBack(back),
    mCurrentImage(&mImage) {
    // 初始化成员
    mImage2.load(QString(Const::IMAGE_FILE_PATH).arg(type * 10 + 1));
}

/**
 * 析构方法。
 */
Box::~Box() {
    delete mBack;
}

/**
 * 移动。
 * @param direction     方向
 * @param moveResult    移动结果
 * @return 被推动的箱子
 */
BaseGameObject* Box::move(int direction, MoveResult* moveResult) {
    bool leftFromDest = false;  // 是否离开目的地
    int destX = mX, destY = mY; // 新位置的坐标

    // 计算新位置
    if (direction == Qt::Key_Left) {
        destX--;
    } else if (direction == Qt::Key_Right) {
        destX++;
    } else if (direction == Qt::Key_Up) {
        destY--;
    } else if (direction == Qt::Key_Down) {
        destY++;
    }

    // 如果旁边是墙或箱子，则直接返回
    if (Game::sBaseGameObjects[destY][destX]->getType() == WALL ||
        Game::sBaseGameObjects[destY][destX]->getType() == BOX) {
        *moveResult = NO_MOVE;
        return this;
    }

    // 设置移动结果
    if (*moveResult < NORMAL_MOVED) {
        *moveResult = NORMAL_MOVED;
    }

    // 判断是否要离开目的地
    if (mType == BOX && mBack->getType() == DESTINATION) {
        leftFromDest = true;
        *moveResult = LEFT_FROM_DEST;
        mCurrentImage = &mImage;
    }

    // 用背后对象擦除自己
    mBack->draw();
    Game::sBaseGameObjects[mY][mX] = mBack;

    // 计算新位置
    mX = destX;
    mY = destY;

    // 设置新的背后对象
    mBack = Game::sBaseGameObjects[mY][mX];

    // 判断是否到达目的地
    if (mType == BOX && mBack->getType() == DESTINATION) {
        if (leftFromDest) {
            *moveResult = NORMAL_MOVED;
        } else {
            *moveResult = ARRIVED_ON_DEST;
        }
        mCurrentImage = &mImage2;
    }

    // 重绘自己
    mDrawer.begin(mBitmap);
    mDrawer.drawImage(mX * Const::GRID_SIZE, mY * Const::GRID_SIZE, *mCurrentImage);
    mDrawer.end();

    // 将自己保存到数组中
    Game::sBaseGameObjects[mY][mX] = this;

    return this;
}
